package com.lws.rxutils.asynconce;

import android.view.View;

import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidDisposable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewModel;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.disposables.DisposableContainer;
import io.reactivex.rxjava3.functions.Action;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class FlowableRxAsyncOnce<T> {

    private final Flowable<T> flowable;

    FlowableRxAsyncOnce(@NonNull Flowable<T> flowable) {
        this.flowable = flowable.subscribeOn(Schedulers.io());
    }

    @CheckResult
    @NonNull
    public Disposable start(@NonNull Consumer<? super T> onNext) {
        return flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext);
    }

    @CheckResult
    @NonNull
    public Disposable start(@NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError) {
        return flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext, onError);
    }

    @CheckResult
    @NonNull
    public Disposable start(@NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError, @NonNull Action onComplete) {
        return flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext, onError, onComplete);
    }


    public void start(@NonNull DisposableContainer container, @NonNull Consumer<? super T> onNext) {
        flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext, Debug::logOnThrowable, Debug::logonComplete, container);
    }

    public void start(@NonNull DisposableContainer container, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError) {
        flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext, onError, Debug::logonComplete, container);
    }


    public void start(@NonNull DisposableContainer container, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError, @NonNull Action onComplete) {
        flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext, onError, onComplete, container);
    }


    public void start(@NonNull LifecycleOwner lifecycleOwner, @NonNull Consumer<? super T> onNext) {
        flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext, Debug::logOnThrowable, Debug::logonComplete, AndroidDisposable.from(lifecycleOwner));
    }

    public void start(@NonNull LifecycleOwner lifecycleOwner, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError) {
        flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext, onError, Debug::logonComplete, AndroidDisposable.from(lifecycleOwner));
    }


    public void start(@NonNull LifecycleOwner lifecycleOwner, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError, @NonNull Action onComplete) {
        flowable.observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNext, onError, onComplete, AndroidDisposable.from(lifecycleOwner));
    }


    public void start(@NonNull Lifecycle lifecycle, @NonNull Consumer<? super T> onNext) {
        start(AndroidDisposable.from(lifecycle), onNext);
    }

    public void start(@NonNull Lifecycle lifecycle, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError) {
        start(AndroidDisposable.from(lifecycle), onNext, onError);
    }


    public void start(@NonNull Lifecycle lifecycle, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError, @NonNull Action onComplete) {
        start(AndroidDisposable.from(lifecycle), onNext, onError, onComplete);
    }


    public void start(@NonNull ViewModel viewModel, @NonNull Consumer<? super T> onNext) {
        start(AndroidDisposable.from(viewModel), onNext);
    }

    public void start(@NonNull ViewModel viewModel, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError) {
        start(AndroidDisposable.from(viewModel), onNext, onError);
    }


    public void start(@NonNull ViewModel viewModel, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError, @NonNull Action onComplete) {
        start(AndroidDisposable.from(viewModel), onNext, onError, onComplete);
    }


    public void start(@NonNull View view, @NonNull Consumer<? super T> onNext) {
        start(AndroidDisposable.from(view), onNext);
    }

    public void start(@NonNull View view, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError) {
        start(AndroidDisposable.from(view), onNext, onError);
    }


    public void start(@NonNull View view, @NonNull Consumer<? super T> onNext, @NonNull Consumer<Throwable> onError, @NonNull Action onComplete) {
        start(AndroidDisposable.from(view), onNext, onError, onComplete);
    }


}
